package com.itlong.cloud.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.itlong.cloud.POJO.DTO.app.AppGetDateListPageDTO;
import com.itlong.cloud.POJO.DTO.app.AppGetPassRecordListPageDTO;
import com.itlong.cloud.POJO.DTO.app.AppUploadRecordJsonDTO;
import com.itlong.cloud.POJO.DTO.smartcard.SmartCardSyncDataPullDTO;
import com.itlong.cloud.POJO.DTO.smartcard.SmartCardSyncDataRecordDTO;
import com.itlong.cloud.POJO.PO.*;
import com.itlong.cloud.POJO.VO.app.AppGetPassRecordListPageVO;
import com.itlong.cloud.POJO.VO.app.AppUploadPassErrorVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.app.dao.*;
import com.itlong.cloud.app.service.IAppDevicePassRecordService;
import com.itlong.cloud.constants.RabbitMQConstant;
import com.itlong.cloud.enumerate.*;
import com.itlong.cloud.property.dao.IPropertyVisitorPassRecordDao;
import com.itlong.cloud.rabbitmq.config.MessageSender;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.utils.data.handler.SqlUtil;
import com.itlong.cloud.utils.date.DateUtil;
import com.itlong.cloud.utils.file.UploadFileUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import com.itlong.cloud.utils.page.Page;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import sun.misc.BASE64Decoder;

import javax.annotation.PostConstruct;
import java.io.ByteArrayInputStream;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * <desc>
 *      用户通行记录业务处理接口实现类
 * </desc>
 *
 * @createDate 2017/11/09
 */
@Service
@RefreshScope
public class AppDevicePassRecordServiceImpl implements IAppDevicePassRecordService{

    private static final Logger LOG = LoggerFactory.getLogger(AppDevicePassRecordServiceImpl.class);

    @Autowired
    private IAppDevicePassRecordDao iAppDevicePassRecordDao;

    @Autowired
    private IAppDeviceDao iAppDeviceDao;

    @Autowired
    private IAppDeviceEntranceRecordDao iAppDeviceEntranceRecordDao;

    @Autowired
    private IAppDeviceElevatorRecordDao iAppDeviceElevatorRecordDao;

    @Autowired
    private IAppDeviceCloudIntercomRecordDao iAppDeviceCloudIntercomRecordDao;

    @Autowired
    private IPropertyVisitorPassRecordDao iPropertyVisitorPassRecordDao;

    @Autowired
    private MessageSender messageSender;

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    private Lock writeLock;
    private Lock readLock;
    //app设备通行纪录线程池
    private static ExecutorService appDevicePassRecordThreadPool = Executors.newFixedThreadPool(10);

    @PostConstruct
    public void init(){
        writeLock = lock.writeLock();
        readLock=lock.readLock();
    }

    @Value("${" + PlatformConstants.FILE_FTP_HOST + "}")
    public String FILE_FTP_HOST;

    @Value("${" + PlatformConstants.FILE_FTP_PORT + "}")
    public String FILE_FTP_PORT;

    @Value("${" + PlatformConstants.FILE_FTP_USERNAME + "}")
    public String FILE_FTP_USERNAME;

    @Value("${" + PlatformConstants.FILE_FTP_PASSWORD + "}")
    public String FILE_FTP_PASSWORD;

    @Value("${" + PlatformConstants.FILE_ACCESS_URL + "}")
    public String FILE_ACCESS_URL;

    /**
     * <desc>
     *      获取用户有记录的通行日期分页列表
     * </desc>
     *
     * @param dto dto参数实体
     * @return
     * @author Jiaqi.X
     * @createDate 2017/11/09
     */
    @Override
    public Page<String> getPassDateListPage(AppGetDateListPageDTO dto) throws Exception {
        //将DTO转换为Map params
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(dto);
        //分页类默认pageSize为20
        Page<String> page = new Page<>();
        page.getPage().setPageSize(dto.getPageSize());
        page.getPage().setCurrentPage(dto.getPageNo());
        params.put("currentPage",page.getPage().getStartSlip());
        params.put("pageSize",page.getPage().getPageSize());
        params.put("loginUserId",dto.getLoginUserId());
        if(StringUtils.isNotBlank(dto.getTimeDiff())){
            //判断是否要计算时差
            if(Integer.valueOf(dto.getTimeDiff()) > 0){
                params.put("addOrSub","add");
            }else{
                params.put("addOrSub","sub");
            }
            params.put("timeDiff",Math.abs(Integer.valueOf(dto.getTimeDiff())));
        }
        //填充返回数据集
        page.setRows(iAppDevicePassRecordDao.getPassDateListPage(params), iAppDevicePassRecordDao.getPassDateListPageCount(params));
        return page;
    }




    /**
     * <desc>
     *      获取用户通行记录
     * </desc>
     *
     * @param dto 参数dto类
     * @return
     * @author Jiaqi.X
     * @createDate 2017/11/09
     */
    @Override
    public Page<AppGetPassRecordListPageVO> getPage(AppGetPassRecordListPageDTO dto) throws Exception {
        //将DTO转换为Map params
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(dto);
        //分页类默认pageSize为20
        Page<AppGetPassRecordListPageVO> page = new Page<>();
        page.getPage().setPageSize(dto.getPageSize());
        page.getPage().setCurrentPage(dto.getPageNo());
        params.put("currentPage",page.getPage().getStartSlip());
        params.put("pageSize",page.getPage().getPageSize());
        if(StringUtils.isNotBlank(dto.getTimeDiff())){
            //判断是否要计算时差
            if(Integer.valueOf(dto.getTimeDiff()) > 0){
                params.put("addOrSub","add");
            }else{
                params.put("addOrSub","sub");
            }
            params.put("timeDiff",Math.abs(Integer.valueOf(dto.getTimeDiff())));
        }
        //填充返回数据集
        page.setRows(iAppDevicePassRecordDao.getPage(params), iAppDevicePassRecordDao.getPageCount(params));
        return page;
    }

    /**
     * <desc>
     *      获取通行记录列表，app2.0版本新增
     * </desc>
     *
     * @param projectId 项目编号
     * @param pageIndex 当前页数(每页15条)
     * @param userId    用户id
     * @return 通行记录列表
     * @author wangzhi
     * @createDate 2019/06/18
     */
    @Override
    public Map<String, Object> getOpenDoorRecord(String projectId, String pageIndex, String userId) throws Exception {
        Map<String, Object> params = new HashMap<>();
        Map<String, Object> data = new HashMap<>();
        List<Map<String, Object>> dataAry = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat(DateUtil.YMDSQL);
        Calendar calendar = Calendar.getInstance();
        // 今天
        Date today = sdf.parse(sdf.format(calendar.getTime()));
        // 七天前
        calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - 7);
        Date weekDay = sdf.parse(sdf.format(calendar.getTime()));
        params.put("projectId", projectId);
        params.put("userId", userId);
        // 分页索引
        if (Integer.parseInt(pageIndex) > 0) {
            params.put("startSlip", (Integer.parseInt(pageIndex) - 1) * 15);
        } else {
            params.put("startSlip", 0);
        }
        // 分页记录数
        params.put("pageSize", 15);
        data.put("pageCount", 0);
        List<Map<String, Object>> recordAry = iAppDevicePassRecordDao.getOpenDoorRecord(params);
        // 处理返回数据
        if (recordAry != null && !recordAry.isEmpty()) {
            data.put("pageCount", recordAry.size());
            List<Map<String, Object>> aryToday = new ArrayList<>();
            List<Map<String, Object>> aryWeek = new ArrayList<>();
            List<Map<String, Object>> aryAgo = new ArrayList<>();
            for (Map<String, Object> record : recordAry) {
                if (today.compareTo(sdf.parse(record.get("date").toString())) == 0) {
                    aryToday.add(record);
                } else if (weekDay.compareTo(sdf.parse(record.get("date").toString())) <= 0) {
                    aryWeek.add(record);
                } else {
                    aryAgo.add(record);
                }
            }
            if (!aryToday.isEmpty()) {
                Map<String, Object> mapToday = new HashMap<>();
                mapToday.put("title", "今天");
                mapToday.put("recordAry",aryToday);
                dataAry.add(mapToday);
            }
            if (!aryWeek.isEmpty()) {
                Map<String, Object> mapWeek = new HashMap<>();
                mapWeek.put("title", "一周内");
                mapWeek.put("recordAry",aryWeek);
                dataAry.add(mapWeek);
            }
            if (!aryAgo.isEmpty()) {
                Map<String, Object> mapAgo = new HashMap<>();
                mapAgo.put("title", "更早");
                mapAgo.put("recordAry",aryAgo);
                dataAry.add(mapAgo);
            }
        }
        data.put("dataAry", dataAry);
        return data;
    }

    /**
     * <desc>
     *      获取电梯通行记录列表，app2.0版本新增
     * </desc>
     *
     * @param pageNum 当前页数(每页15条)
     * @param userId 用户id
     * @return 通行记录列表
     * @author Qiang.S
     * @createDate 2019/06/26
     */
    @Override
    public Map<String, Object> getLiftHistory(String pageNum, String userId) throws Exception {
        Map<String, Object> params = new HashMap<>();
        Map<String, Object> data = new HashMap<>();
        List<Map<String, Object>> dataAry = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat(DateUtil.YMDSQL);
        Calendar calendar = Calendar.getInstance();
        // 今天
        Date today = sdf.parse(sdf.format(calendar.getTime()));
        // 七天前
        calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - 7);
        Date weekDay = sdf.parse(sdf.format(calendar.getTime()));
        params.put("userId", userId);
        // 分页索引
        if (Integer.parseInt(pageNum) > 0) {
            params.put("startSlip", (Integer.parseInt(pageNum) - 1) * 15);
        } else {
            params.put("startSlip", 0);
        }
        // 分页记录数
        params.put("pageSize", 15);
        data.put("pageCount", 0);
        List<Map<String, Object>> recordAry = iAppDevicePassRecordDao.getLiftHistory(params);
        // 处理返回数据
        if (recordAry != null && !recordAry.isEmpty()) {
            data.put("pageCount", recordAry.size());
            List<Map<String, Object>> aryToday = new ArrayList<>();
            List<Map<String, Object>> aryWeek = new ArrayList<>();
            List<Map<String, Object>> aryAgo = new ArrayList<>();
            for (Map<String, Object> record : recordAry) {
                if (today.compareTo(sdf.parse(record.get("date").toString())) == 0) {
                    aryToday.add(record);
                } else if (weekDay.compareTo(sdf.parse(record.get("date").toString())) <= 0) {
                    aryWeek.add(record);
                } else {
                    aryAgo.add(record);
                }
            }
            if (!aryToday.isEmpty()) {
                Map<String, Object> mapToday = new HashMap<>();
                mapToday.put("title", "今天");
                mapToday.put("recordAry",aryToday);
                dataAry.add(mapToday);
            }
            if (!aryWeek.isEmpty()) {
                Map<String, Object> mapWeek = new HashMap<>();
                mapWeek.put("title", "一周内");
                mapWeek.put("recordAry",aryWeek);
                dataAry.add(mapWeek);
            }
            if (!aryAgo.isEmpty()) {
                Map<String, Object> mapAgo = new HashMap<>();
                mapAgo.put("title", "更早");
                mapAgo.put("recordAry",aryAgo);
                dataAry.add(mapAgo);
            }
        }
        data.put("dataAry", dataAry);
        return data;
    }

    /**
     * <desc>
     *      获取访客通行密码邀请记录
     * </desc>
     *
     * @param projectId 项目编号
     * @param pageNo    页数
     * @param pageSize  每页数
     * @param userId    用户id
     * @return 访客通行密码邀请记录
     * @author wangzhi
     * @createDate 2019/06/24
     */
    @Override
    public Map<String, Object> getInviteRecord(String projectId, String pageNo, String pageSize, String userId) throws Exception {
        Map<String, Object> params = new HashMap<>();
        Map<String, Object> data = new HashMap<>();
        List<Map<String, Object>> dataAry = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");
        Calendar calendar = Calendar.getInstance();
        // 今天
        Date today = sdf.parse(sdf.format(calendar.getTime()));
        // 七天前
        calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - 7);
        Date weekDay = sdf.parse(sdf.format(calendar.getTime()));
        params.put("projectId", projectId);
        params.put("userId", userId);
        // 分页索引
        if (Integer.parseInt(pageNo) > 0) {
            params.put("startSlip", (Integer.parseInt(pageNo) - 1) * Integer.parseInt(pageSize));
        } else {
            params.put("startSlip", 0);
        }
        // 分页记录数
        params.put("pageSize", Integer.parseInt(pageSize));
        data.put("pageCount", 0);
        List<Map<String, Object>> recordAry = iPropertyVisitorPassRecordDao.getInviteRecord(params);
        // 处理返回数据
        if (recordAry != null && !recordAry.isEmpty()) {
            data.put("pageCount", recordAry.size());
            List<Map<String, Object>> aryToday = new ArrayList<>();
            List<Map<String, Object>> aryWeek = new ArrayList<>();
            List<Map<String, Object>> aryAgo = new ArrayList<>();
            for (Map<String, Object> record : recordAry) {
                if (today.compareTo(sdf.parse(record.get("invateDate").toString())) == 0) {
                    aryToday.add(record);
                } else if (weekDay.compareTo(sdf.parse(record.get("invateDate").toString())) <= 0) {
                    aryWeek.add(record);
                } else {
                    aryAgo.add(record);
                }
            }
            if (!aryToday.isEmpty()) {
                Map<String, Object> mapToday = new HashMap<>();
                mapToday.put("title", "今天");
                mapToday.put("recordAry",aryToday);
                dataAry.add(mapToday);
            }
            if (!aryWeek.isEmpty()) {
                Map<String, Object> mapWeek = new HashMap<>();
                mapWeek.put("title", "一周内");
                mapWeek.put("recordAry",aryWeek);
                dataAry.add(mapWeek);
            }
            if (!aryAgo.isEmpty()) {
                Map<String, Object> mapAgo = new HashMap<>();
                mapAgo.put("title", "更早");
                mapAgo.put("recordAry",aryAgo);
                dataAry.add(mapAgo);
            }
        }
        data.put("dataAry", dataAry);
        return data;
    }

    /**
     * <desc>
     * 访客详情
     * </desc>
     *
     * @param passId
     * @return
     * @author caoshuai
     * @createDate 2021/1/21 15:47
     */
    @Override
    public Map<String, Object> getVisitorsInfo(String passId) {

        Map<String, Object> visitorsInfo = iPropertyVisitorPassRecordDao.getVisitorsInfo(passId);
        if(null != visitorsInfo) {
            visitorsInfo.put("effectiveTime", visitorsInfo.get("startTime") + "-" + visitorsInfo.get("endTime"));
        }
        if(null == visitorsInfo || null == visitorsInfo.get("deviceUniques") || StringUtils.isBlank(visitorsInfo.get("deviceUniques") + "")) {
            return visitorsInfo;
        }
        String deviceUniques = visitorsInfo.get("deviceUniques") + "";

        List elevatorList = new ArrayList();
        List entranceList = new ArrayList();
        List intercomList = new ArrayList();
        List padList = new ArrayList();
        List controllerList = new ArrayList();
        for (String deviceUnique :deviceUniques.split(",")){
            Integer type = StringHandlerUtil.getDeviceTypeByDeviceUnique(deviceUnique);
            switch (type){
                case 1:
                    elevatorList.add(deviceUnique);
                    break;
                case 2:
                    entranceList.add(deviceUnique);
                    break;
                case 3:
                    intercomList.add(deviceUnique);
                    break;
                case 4:
                    padList.add(deviceUnique);
                    break;
                case 5:
                    controllerList.add(deviceUnique);
                    break;
                default:
                    break;
            }
        }
        Map<String, Object> param = new HashMap();
        StringBuffer sb = new StringBuffer();
        if(elevatorList.size() > 0) {
            param.put("type", 1);
            param.put("list", elevatorList);
            String deviceNames =iPropertyVisitorPassRecordDao.getDeviceNameByMap(param);
            sb.append("," + deviceNames);
        }
        if(entranceList.size() > 0) {
            param.put("type", 2);
            param.put("list", entranceList);
            String deviceNames =iPropertyVisitorPassRecordDao.getDeviceNameByMap(param);
            sb.append("," + deviceNames);
        }

        if(intercomList.size() > 0) {
            param.put("type", 3);
            param.put("list", intercomList);
            String deviceNames =iPropertyVisitorPassRecordDao.getDeviceNameByMap(param);
            sb.append("," + deviceNames);
        }

        if(padList.size() > 0) {
            param.put("type", 4);
            param.put("list", padList);
            String deviceNames =iPropertyVisitorPassRecordDao.getDeviceNameByMap(param);
            sb.append("," + deviceNames);
        }

        if(controllerList.size() > 0) {
            param.put("type", 5);
            param.put("list", controllerList);
            String deviceNames =iPropertyVisitorPassRecordDao.getDeviceNameByMap(param);
            sb.append("," + deviceNames);
        }
        visitorsInfo.put("deviceNames", sb.toString().substring(1, sb.toString().length()));
        return visitorsInfo;
    }
    /**
     * <desc>
     *      上传用户通行记录
     * </desc>
     *
     * @param userId   用户id
     * @param recordJson json数据串
     * @param projectId 项目id
     * @return
     * @author Jiaqi.X
     * @createDate 2017/11/10
     */
    @Override
    public List<AppUploadPassErrorVO> uploadRecord(String userId,String projectId,String recordJson,String imageStr,String imageType) throws Exception {
        List<AppUploadRecordJsonDTO> dtos= JsonUtil.decode(recordJson, new TypeReference<List<AppUploadRecordJsonDTO>>(){});
        String imageUrl = "";
        if(StringUtils.isNotEmpty(imageStr)){
            try {
                imageStr = URLDecoder.decode(imageStr, "UTF-8");
                BASE64Decoder decoder = new BASE64Decoder();
                byte[] bytes = decoder.decodeBuffer(imageStr);
                ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
                UploadFileUtil.UploadFile uploadFileUtil = new UploadFileUtil().new UploadFile(
                        FILE_FTP_HOST,
                        FILE_FTP_USERNAME,
                        FILE_FTP_PASSWORD,
                        FILE_FTP_PORT,
                        byteArrayInputStream,
                        imageType,
                        FILE_ACCESS_URL,
                        FileCatalogEnum.APPLOGO_FILE.getType()
                );
                Map<String, Object> resultMap = UploadFileUtil.uploadFile(uploadFileUtil);
                if ("true".equals(resultMap.get("returnCode").toString())){
                    imageUrl = resultMap.get("accessPath").toString();
                }else {
                    throw new DataAccessException("【APP端】云对讲开门上传图片失败");
                }
            }catch (Exception e){
                throw new DataAccessException("【APP端】云对讲开门上传图片失败",e);
            }
        }
        //推送一卡通的集合
        List<SmartCardSyncDataRecordDTO> pushToSmartCardRecordList=new ArrayList<>();
        //失败数据的集合
        List<AppUploadPassErrorVO> errorList=new ArrayList<>();
        //批量上传的通行记录
        List<TimeTaskDevicePassRecordPO> devicePassRecords = new ArrayList<>();
        for(AppUploadRecordJsonDTO dto:dtos){
            if(!dto.getDeviceUnique().isEmpty()&&dto.getPassTime()!=null&&dto.getOpenType()!=null&&dto.getDeviceUnique().substring(0, 8).equals(projectId)) {
                //验证是否是完整信息
                TimeTaskDevicePassRecordPO po = new TimeTaskDevicePassRecordPO();
                po.setPdId(LogicIdUtil.bussinessId());
                po.setUserId(userId);
                po.setProjectId(dto.getDeviceUnique().substring(0, 8));
                po.setDeviceUnique(dto.getDeviceUnique());
                po.setPassTime(DateUtil.formatLong(dto.getPassTime()));
                po.setDeviceName(dto.getDeviceName());
                po.setOpenType(dto.getOpenType());
                po.setOpenCount(dto.getOpenCount());
                po.setStatus(DataStatusEnum.NORMAL.getType());
                po.setUploadTime(new Date());
                po.setCreateTime(po.getUploadTime());
                po.setSynchro(0);
                po.setIsOpen(0);
                //检查是否是门禁类型
                if(po.getDeviceUnique().substring(8,9).equals(PropertyEquipTypeEnum.ENTRANCE.getType().toString())){
                    po.setDeviceType(PropertyEquipTypeEnum.ENTRANCE.getType());
                    po.setCorrelationId(dto.getCorrelationId());
                }else if(po.getDeviceUnique().substring(8,9).equals(PropertyEquipTypeEnum.ELEVATOR.getType().toString())){//检查是否是电梯类型
                    po.setDeviceType(PropertyEquipTypeEnum.ELEVATOR.getType());
                    po.setCorrelationId(dto.getCorrelationId());
                }else if(po.getDeviceUnique().substring(8,9).equals(PropertyEquipTypeEnum.CLOUD_INTERCOM.getType().toString())){//检查是否是云对讲类型
                    po.setDeviceType(PropertyEquipTypeEnum.CLOUD_INTERCOM.getType());
                    po.setFacePicUrl(imageUrl);
                }
                //查询设备名称
                if(StringUtils.isBlank(po.getDeviceName()) && StringUtils.isNotBlank(po.getDeviceUnique()) && po.getDeviceType()!=null){
                    po.setDeviceName(iAppDevicePassRecordDao.getDeviceNameByDeviceUnique(po.getDeviceUnique(),po.getDeviceType()));
                }
                Integer isEntranceExists = 0;
                //蓝牙+IOT通行方式标记
                boolean mark = false;
                //判断是否已有该条通行记录
                if((po.getDeviceType() == PropertyEquipTypeEnum.ENTRANCE.getType() || po.getDeviceType() == PropertyEquipTypeEnum.ELEVATOR.getType()) && StringUtils.isNotBlank(po.getCorrelationId())){
                    isEntranceExists = iAppDevicePassRecordDao.queryEntrancePassIsExists(po.getCorrelationId());
                    if(isEntranceExists>0){
                        mark = true;
                        //当IOT通行方式已经入库，需将能行方式改为 蓝牙+IOT 并推送给一卡通
                        iAppDevicePassRecordDao.updateOpenType(po.getCorrelationId());
                        //此处需注意处理 有可能通行记录已同步至设备子表中，故需在此处理子表通行方式
                        if(po.getDeviceType() == PropertyEquipTypeEnum.ENTRANCE.getType()){
                            iAppDevicePassRecordDao.updateEntranceOpenType(dto.getDeviceUnique(), DateUtil.fomatDate(DateUtil.formatLong(dto.getPassTime())),userId);
                        }
                        if(po.getDeviceType() == PropertyEquipTypeEnum.ELEVATOR.getType()){
                            iAppDevicePassRecordDao.updateElevatorOpenType(dto.getDeviceUnique(), DateUtil.fomatDate(DateUtil.formatLong(dto.getPassTime())),userId);
                        }
                    }
                }
                if(po.getDeviceType()!=null){
                    if(!mark){
                        devicePassRecords.add(po);
                    }
                    //发送
                    //需要推送一卡通的通行记录
                    SmartCardSyncDataRecordDTO card=new SmartCardSyncDataRecordDTO();
                    card.setUserId(userId);
                    card.setDeviceUnique(dto.getDeviceUnique());
                    card.setOpenType(dto.getOpenType());
                    card.setPassTime(DateUtil.formatLong(dto.getPassTime()));
                    card.setUploadTime(po.getUploadTime());
                    card.setIsOpen(po.getIsOpen());
                    card.setBeginVisitTime(po.getBeginVisitTime());
                    card.setEndVisitTime(po.getEndVisitTime());
                    card.setOpenCount(po.getOpenCount());
                    card.setUserPhone(dto.getPhoneNo());
                    pushToSmartCardRecordList.add(card);

                }else{
                    AppUploadPassErrorVO appUploadPassErrorVO=new AppUploadPassErrorVO();
                    appUploadPassErrorVO.setDeviceName(dto.getDeviceName());
                    appUploadPassErrorVO.setDeviceUnique(dto.getDeviceUnique());
                    appUploadPassErrorVO.setPassTime(dto.getPassTime().toString());
                    errorList.add(appUploadPassErrorVO);
                }
            }else{
                AppUploadPassErrorVO appUploadPassErrorVO=new AppUploadPassErrorVO();
                appUploadPassErrorVO.setDeviceName(dto.getDeviceName());
                appUploadPassErrorVO.setDeviceUnique(dto.getDeviceUnique());
                appUploadPassErrorVO.setPassTime(dto.getPassTime().toString());
                errorList.add(appUploadPassErrorVO);
            }
        }
        List<Map<String,Object>> datas=SqlUtil.durableDataList(devicePassRecords, PlatformConstants.TABLE_SAVE);


        if (!pushToSmartCardRecordList.isEmpty()){
            if(devicePassRecords!=null && !devicePassRecords.isEmpty()){
                //保存通行记录
                iAppDevicePassRecordDao.batchInsert(devicePassRecords);
            }
            //将通行记录推送给一卡通
            String data = JSON.toJSONString(pushToSmartCardRecordList);
            //数据类型
            SmartCardSyncDataTypeEnum dataType = SmartCardSyncDataTypeEnum.PASS_RECORD_DATA;
            //打包
            SmartCardSyncDataPullDTO smartCardSyncDataPullDTO = new SmartCardSyncDataPullDTO(projectId, data,
                    SmartCardSyncDataOperTypeEnum.ADD, dataType);
            JSONObject dataJs = new JSONObject();
            dataJs.put("data",JSONObject.toJSON(smartCardSyncDataPullDTO));
            messageSender.send(RabbitMQConstant.RABBITMQ_SMARTCARD_SAVE_MODIFY_QUEUE,JsonUtil.toJSON(dataJs),
                    RabbitMQConstant.RABBITMQ_SMARTCARD_SAVE_EXCHANGE, RabbitMQConstant.RABBITMQ_SMARTCARD_SAVE_MODIFY_ROUTING_KEY);
        }

        return errorList;
    }

    /**
     * <desc>
     *       同步通行记录至具体设备通行记录表
     * </desc>
     *
     * @author Jiaqi.X
     * @createDate 2017/11/10
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public  void timeTaskSychro() throws Exception {

        appDevicePassRecordThreadPool.execute(() -> {
            try {
                //需要同步的通行记录id
                List<String> pdIdList=new ArrayList<>();
                //获取待同步的记录集合
                List<TimeTaskDevicePassRecordPO> list=null;
                try {
                    readLock.lock();
                    list = iAppDevicePassRecordDao.getWaitSynchroList();
                }finally {
                    readLock.unlock();
                }
                list.forEach(pass->{
                    pdIdList.add(pass.getPdId());
                });
                if(pdIdList!=null && !pdIdList.isEmpty()) {
                    try {
                        writeLock.lock();
                        iAppDevicePassRecordDao.updateSynchroStatus(pdIdList.toArray(new String[pdIdList.size()]));
                    } finally {
                        writeLock.unlock();
                    }
                }
                for(TimeTaskDevicePassRecordPO record:list){
                    if(record.getDeviceType()==PropertyEquipTypeEnum.ENTRANCE.getType() || PropertyEquipTypeEnum.CLOUD_ENTRANCE.getType().equals(record.getDeviceType())){
                        //门禁通行记录
                        //如果开门方式为访客动态密码和访客二维码方式和访客人脸需将该访客的通行记录保存至visitor_pass_record表中
                        if(record.getOpenType() == OpenTypeEnum.BY_DYNAMIC_PASSWORD.getType() || record.getOpenType() == OpenTypeEnum.BY_VISTOR_QRCODE.getType() || record.getOpenType() == OpenTypeEnum.BY_VISITOR_FACE.getType()
                                || record.getOpenType() == OpenTypeEnum.BY_VISITOR_IDCARD_KEY.getType()){
                            VisitorPassRecordPO visitorPassRecordPO = new VisitorPassRecordPO();
                            String passId = "";
                            if(StringUtils.isNotEmpty(record.getDynamicPassword())){
                                passId = iPropertyVisitorPassRecordDao.getPassIdByVisitor(record.getDynamicPassword(),record.getQrcode(),record.getProjectId());
                            }
                            if(record.getOpenType()== OpenTypeEnum.BY_VISTOR_QRCODE.getType() && StringUtils.isNotEmpty(record.getQrcode())){
                                passId = iPropertyVisitorPassRecordDao.getPassIdByVisitor(record.getDynamicPassword(), record.getQrcode(), record.getProjectId());
                            }
                            if(record.getOpenType()== OpenTypeEnum.BY_VISITOR_FACE.getType() && StringUtils.isNotEmpty(record.getFacePicUrl())){
                                passId = iPropertyVisitorPassRecordDao.getPassId(record.getDynamicPassword(), record.getQrcode(), record.getUserId(), record.getProjectId());
                            }
                            if(record.getOpenType()== OpenTypeEnum.BY_VISITOR_IDCARD_KEY.getType() && StringUtils.isNotEmpty(record.getUserId())){
                                passId = record.getUserId();
                            }
                            if(StringUtils.isNotBlank(record.getPassId())){
                                passId = record.getPassId();
                            }
                            if (StringUtils.isNotBlank(record.getVisitorUuid()) && StringUtils.isBlank(passId)) {
                                passId = iPropertyVisitorPassRecordDao.getPassIdByVisitorPhone(record.getVisitorUuid(), record.getProjectId());
                                if (StringUtils.isBlank(passId)) {
                                    passId = iPropertyVisitorPassRecordDao.getPassIdByVisitorUuid(record.getVisitorUuid(), record.getProjectId());
                                }
                            }
                            visitorPassRecordPO.setProjectId(record.getProjectId());
                            visitorPassRecordPO.setDeviceUnique(record.getDeviceUnique());
                            if(record.getOpenType()==OpenTypeEnum.BY_DYNAMIC_PASSWORD.getType()){
                                visitorPassRecordPO.setPassType(1);
                            }
                            if(record.getOpenType()==OpenTypeEnum.BY_VISTOR_QRCODE.getType()){
                                visitorPassRecordPO.setPassType(2);
                            }
                            if(record.getOpenType()==OpenTypeEnum.BY_VISITOR_FACE.getType()){
                                visitorPassRecordPO.setPassType(3);
                            }
                            if(record.getOpenType()==OpenTypeEnum.BY_VISITOR_IDCARD_KEY.getType()){
                                visitorPassRecordPO.setPassType(4);
                            }
                            visitorPassRecordPO.setFacePicUrl(record.getFacePicUrl());
                            visitorPassRecordPO.setPassTime(record.getPassTime());
                            visitorPassRecordPO.setStatus(1);
                            visitorPassRecordPO.setCreateTime(new Date());
                            visitorPassRecordPO.setUpdateTime(new Date());
                            visitorPassRecordPO.setPassId(passId);
                            visitorPassRecordPO.setQrcodeSource(record.getQrcodeSource());
                            visitorPassRecordPO.setOnline(record.getOnline());
                            visitorPassRecordPO.setTimescount(record.getTimescount());
                            iPropertyVisitorPassRecordDao.save(SqlUtil.durableData(visitorPassRecordPO, PlatformConstants.TABLE_SAVE));
                        }else{
                            DeviceEntranceRecordPO entrance=new DeviceEntranceRecordPO();
                            entrance.setDeviceUnique(record.getDeviceUnique());
                            entrance.setOpenType(record.getOpenType());
                            entrance.setPassTime(record.getPassTime());
                            entrance.setUploadTime(record.getUploadTime());
                            entrance.setOpenCount(record.getOpenCount());
                            if (StringUtils.isBlank(record.getUserId())) {
                                String userId = iAppDeviceEntranceRecordDao.getUserIdByPhoneNum(record.getVisitorUuid());
                                record.setUserId(userId);
                            }
                            entrance.setTimescount(record.getTimescount());
                            entrance.setLastPassCount(record.getLastPassCount());
                            entrance.setUserId(record.getUserId());
                            entrance.setStatus(1);
                            entrance.setCreateTime(new Date());
                            entrance.setProjectId(record.getProjectId());
                            entrance.setFacePicUrl(record.getFacePicUrl());
                            entrance.setTimescount(record.getTimescount());
                            entrance.setLastPassCount(record.getLastPassCount());
                            entrance.setQrcodeSource(record.getQrcodeSource());
                            entrance.setOnline(record.getOnline());
                            entrance.setRoomDetail(record.getRoomDetail());
                            if("1,2,3,20".contains(record.getOpenType() + "")) {
                                entrance.setSource(4);
                            } else {
                                entrance.setSource(record.getSource());
                            }
                            iAppDeviceEntranceRecordDao.save(SqlUtil.durableData(entrance, PlatformConstants.TABLE_SAVE));
                        }
                    }else if(record.getDeviceType() == PropertyEquipTypeEnum.ELEVATOR.getType() ||
                            record.getDeviceType() == PropertyEquipTypeEnum.CLOUD_PASS_RECORD_ELEVATOR.getType()){

                        //如果开门方式为访客动态密码和访客二维码和访客人脸方式需将该访客的通行记录保存至visitor_pass_record表中
                        if(record.getOpenType() == OpenTypeEnum.BY_DYNAMIC_PASSWORD.getType() || record.getOpenType() == OpenTypeEnum.BY_VISTOR_QRCODE.getType() || record.getOpenType() == OpenTypeEnum.BY_VISITOR_FACE.getType()
                                || record.getOpenType() == OpenTypeEnum.BY_VISITOR_IDCARD_KEY.getType()){
                            VisitorPassRecordPO visitorPassRecordPO = new VisitorPassRecordPO();
                            String passId = "";
                            if(StringUtils.isNotEmpty(record.getDynamicPassword())){
                                passId = iPropertyVisitorPassRecordDao.getPassId(record.getDynamicPassword(),record.getQrcode(),record.getUserId(),record.getProjectId());
                            }
                            if(record.getOpenType()== OpenTypeEnum.BY_VISTOR_QRCODE.getType() && StringUtils.isNotEmpty(record.getQrcode())){
                                passId = iPropertyVisitorPassRecordDao.getPassId(record.getDynamicPassword(),record.getQrcode(),record.getUserId(),record.getProjectId());
                            }
                            if(record.getOpenType()== OpenTypeEnum.BY_VISITOR_FACE.getType() && StringUtils.isNotEmpty(record.getFacePicUrl())){
                                passId = iPropertyVisitorPassRecordDao.getPassId(record.getDynamicPassword(),record.getQrcode(),record.getUserId(),record.getProjectId());
                            }
                            if(record.getOpenType()== OpenTypeEnum.BY_VISITOR_IDCARD_KEY.getType() && StringUtils.isNotEmpty(record.getUserId())){
                                passId = record.getUserId();
                            }
                            if(StringUtils.isNotBlank(record.getPassId())){
                                passId = record.getPassId();
                            }
                            visitorPassRecordPO.setProjectId(record.getProjectId());
                            visitorPassRecordPO.setDeviceUnique(record.getDeviceUnique());
                            if(record.getOpenType()==OpenTypeEnum.BY_DYNAMIC_PASSWORD.getType()){
                                visitorPassRecordPO.setPassType(1);
                            }
                            if(record.getOpenType()==OpenTypeEnum.BY_VISTOR_QRCODE.getType()){
                                visitorPassRecordPO.setPassType(2);
                            }
                            if(record.getOpenType()==OpenTypeEnum.BY_VISITOR_FACE.getType()){
                                visitorPassRecordPO.setPassType(3);
                                visitorPassRecordPO.setFacePicUrl(record.getFacePicUrl());
                            }
                            if(record.getOpenType()==OpenTypeEnum.BY_VISITOR_IDCARD_KEY.getType()){
                                visitorPassRecordPO.setPassType(4);
                            }
                            visitorPassRecordPO.setPassTime(record.getPassTime());
                            visitorPassRecordPO.setStatus(1);
                            visitorPassRecordPO.setCreateTime(new Date());
                            visitorPassRecordPO.setUpdateTime(new Date());
                            visitorPassRecordPO.setPassId(passId);
                            visitorPassRecordPO.setQrcodeSource(record.getQrcodeSource());
                            visitorPassRecordPO.setOnline(record.getOnline());
                            visitorPassRecordPO.setTimescount(record.getTimescount());
                            iPropertyVisitorPassRecordDao.save(SqlUtil.durableData(visitorPassRecordPO, PlatformConstants.TABLE_SAVE));
                        }else{
                            //电梯通行记录
                            DeviceElevatorRecordPO elevator=new DeviceElevatorRecordPO();
                            elevator.setDeviceUnique(record.getDeviceUnique());
                            elevator.setOpenType(record.getOpenType());
                            elevator.setPassTime(record.getPassTime());
                            elevator.setUploadTime(record.getUploadTime());
                            elevator.setOpenCount(record.getOpenCount());
                            elevator.setUserId(record.getUserId());
                            elevator.setStatus(1);
                            elevator.setCreateTime(new Date());
                            elevator.setProjectId(record.getProjectId());
                            elevator.setFacePicUrl(record.getFacePicUrl());
                            elevator.setTimescount(record.getTimescount());
                            elevator.setLastPassCount(record.getLastPassCount());
                            elevator.setQrcodeSource(record.getQrcodeSource());
                            elevator.setOnline(record.getOnline());
                            elevator.setRoomDetail(record.getRoomDetail());
                            if("1,2,3,20".contains(record.getOpenType() + "")) {
                                elevator.setSource(4);
                            } else {
                                elevator.setSource(record.getSource());
                            }

                            elevator.setFromFloor(record.getFromFloor());
                            elevator.setToFloor(record.getToFloor());
                            iAppDeviceElevatorRecordDao.save(SqlUtil.durableData(elevator, PlatformConstants.TABLE_SAVE));
                        }


                    }else if(record.getDeviceType() == PropertyEquipTypeEnum.CLOUD_INTERCOM.getType()){
                        //云对讲通行记录
                        //开门方式为动态密码和访客二维码和访客人脸方式需将该访客的通行记录保存至visitor_pass_record表中
                        if(record.getOpenType() == OpenTypeEnum.BY_DYNAMIC_PASSWORD.getType() || record.getOpenType() == OpenTypeEnum.BY_VISTOR_QRCODE.getType() || record.getOpenType() == OpenTypeEnum.BY_VISITOR_FACE.getType()
                                || record.getOpenType() == OpenTypeEnum.BY_VISITOR_IDCARD_KEY.getType()){
                            VisitorPassRecordPO visitorPassRecordPO = new VisitorPassRecordPO();
                            String passId = "";
                            if(StringUtils.isNotEmpty(record.getDynamicPassword())){
                                passId = iPropertyVisitorPassRecordDao.getPassId(record.getDynamicPassword(),record.getQrcode(),record.getUserId(),record.getProjectId());
                            }
                            if(record.getOpenType()== OpenTypeEnum.BY_VISTOR_QRCODE.getType() && StringUtils.isNotEmpty(record.getQrcode())){
                                passId = iPropertyVisitorPassRecordDao.getPassId(record.getDynamicPassword(),record.getQrcode(),record.getUserId(),record.getProjectId());
                            }
                            if(record.getOpenType()== OpenTypeEnum.BY_VISITOR_FACE.getType() && StringUtils.isNotEmpty(record.getFacePicUrl())){
                                passId = iPropertyVisitorPassRecordDao.getPassId(record.getDynamicPassword(),record.getQrcode(),record.getUserId(),record.getProjectId());
                            }
                            if(record.getOpenType()== OpenTypeEnum.BY_VISITOR_IDCARD_KEY.getType() && StringUtils.isNotEmpty(record.getUserId())){
                                passId = record.getUserId();
                            }
                            if(StringUtils.isNotBlank(record.getPassId())){
                                passId = record.getPassId();
                            }
                            visitorPassRecordPO.setProjectId(record.getProjectId());
                            visitorPassRecordPO.setDeviceUnique(record.getDeviceUnique());
                            visitorPassRecordPO.setFacePicUrl(record.getFacePicUrl());

                            if(record.getOpenType()==OpenTypeEnum.BY_DYNAMIC_PASSWORD.getType()){
                                visitorPassRecordPO.setPassType(1);
                            }
                            if(record.getOpenType()==OpenTypeEnum.BY_VISTOR_QRCODE.getType()){
                                visitorPassRecordPO.setPassType(2);
                            }
                            if(record.getOpenType()==OpenTypeEnum.BY_VISITOR_FACE.getType()){
                                visitorPassRecordPO.setPassType(3);
                            }
                            if(record.getOpenType()==OpenTypeEnum.BY_VISITOR_IDCARD_KEY.getType()){
                                visitorPassRecordPO.setPassType(4);
                            }
                            visitorPassRecordPO.setPassTime(record.getPassTime());
                            visitorPassRecordPO.setStatus(1);
                            visitorPassRecordPO.setCreateTime(new Date());
                            visitorPassRecordPO.setUpdateTime(new Date());
                            visitorPassRecordPO.setPassId(passId);
                            visitorPassRecordPO.setQrcodeSource(record.getQrcodeSource());
                            visitorPassRecordPO.setOnline(record.getOnline());
                            visitorPassRecordPO.setTimescount(record.getTimescount());
                            iPropertyVisitorPassRecordDao.save(SqlUtil.durableData(visitorPassRecordPO, PlatformConstants.TABLE_SAVE));
                        }else{
                            DeviceCloudIntercomRecordPO cloudIntercom=new DeviceCloudIntercomRecordPO();
                            cloudIntercom.setDeviceUnique(record.getDeviceUnique());
                            cloudIntercom.setOpenType(record.getOpenType());
                            cloudIntercom.setPassTime(record.getPassTime());
                            cloudIntercom.setUploadTime(record.getUploadTime());
                            cloudIntercom.setOpenCount(record.getOpenCount());
                            cloudIntercom.setQqNum(record.getQqNum());
                            cloudIntercom.setRoomNum(record.getRoomNum());
                            cloudIntercom.setIsOpen(record.getIsOpen());
                            cloudIntercom.setBeginVisitTime(record.getBeginVisitTime());
                            if(record.getOpenType()==OpenTypeEnum.BY_QRCODE.getType()){
                                //根据业主二维码查询用户userId
                                String userId = iAppDeviceCloudIntercomRecordDao.getUserIdByQrcode(record.getQrcode());
                                if(StringUtils.isBlank(userId)){
                                    cloudIntercom.setUserId(record.getUserId());
                                }else {
                                    cloudIntercom.setUserId(userId);
                                }
                            }else{
                                cloudIntercom.setUserId(record.getUserId());
                            }
                            cloudIntercom.setEndVisitTime(record.getEndVisitTime());
                            cloudIntercom.setCallPhoneNo(record.getCallPhoneNo());
                            cloudIntercom.setStatus(1);
                            cloudIntercom.setCreateTime(new Date());
                            cloudIntercom.setProjectId(record.getProjectId());
                            cloudIntercom.setFacePicUrl(record.getFacePicUrl());
                            cloudIntercom.setTimescount(record.getTimescount());
                            cloudIntercom.setLastPassCount(record.getLastPassCount());
                            cloudIntercom.setQrcodeSource(record.getQrcodeSource());
                            cloudIntercom.setOnline(record.getOnline());
                            cloudIntercom.setRoomDetail(record.getRoomDetail());
                            if("1,2,3,20".contains(record.getOpenType() + "")) {
                                cloudIntercom.setSource(4);
                            } else {
                                cloudIntercom.setSource(record.getSource());
                            }
                            iAppDeviceCloudIntercomRecordDao.save(SqlUtil.durableData(cloudIntercom, PlatformConstants.TABLE_SAVE));
                        }
                    }
                }
                if(!list.isEmpty()) {
                    //修改所有同步的通行记录的通行状态
                    iAppDevicePassRecordDao.updateSynchro(pdIdList.toArray(new String[pdIdList.size()]));
                }
            } catch (Exception e) {
                LOG.error("同步通行记录至具体设备通行记录异常", e);
            }
        });
    }

    /**
     * <desc>
     *      以用户为基准删除通行时间大于3个月的记录
     * </desc>
     *
     * @author Jiaqi.X
     * @createDate 2017/11/13
     */
    @Override
    public void timeTaskDeleteRecord() {
        //获取通行记录按用户分组最近的一次的通行时间
//        List<TimeTaskDevicePassRecordPO> users = iAppDevicePassRecordDao.getPassRecordUsers();
//        for(TimeTaskDevicePassRecordPO user : users){
//            appDevicePassRecordThreadPool.execute(() -> {
//                if (user.getUserId() != null) {
//                    //删除距离最近一次的通行记录往前3个月之前的数据
//                    Date date = DateUtil.getAddMonth(user.getPassTime(), -3);
//                    iAppDevicePassRecordDao.deleteNeedClearPassRecord(user.getUserId(), DateUtil.fomatDate(date, DateUtil.YMDSQL));
//                }
//            });
//        }
        //删除当前系统时间三个月之前的通行记录临时表数据
        iAppDevicePassRecordDao.deleteThreeMonthAgoData();
    }


}
